package org.restly.core;

import net.sf.oval.Validator;
import net.sf.oval.configuration.annotation.AnnotationsConfigurer;
import net.sf.oval.exception.OValException;
import net.sf.oval.internal.ClassChecks;
import org.restly.ValidateOn;
import org.restly.ValidationType;
import org.restly.servlet.RestlyHttpServletRequest;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Nov 8, 2008, 12:23:58 PM
 *
 * @author <a href="mailto:erik.beeson@gmail.com">Erik Beeson</a>
 */
public class RestlyValidator extends Validator {
	private final RestlyHttpServletRequest request;

	public RestlyValidator(RestlyHttpServletRequest request) {
		super(new AnnotationsConfigurer());

		this.request = request;

		enableAllProfiles();

		if(request.isGet()) disableProfile("write");

		List<String> methods = new ArrayList<String>(Arrays.asList("get", "post", "put", "delete"));
		methods.remove(request.getMethod());
		for(String method : methods) {
			disableProfile(method);
		}
	}

	protected ClassChecks getClassChecks(Class<?> clazz) throws IllegalArgumentException, OValException {
		reconfigureChecks();
		ClassChecks cc = super.getClassChecks(clazz);
		List<Field> fieldsToRemove = new ArrayList<Field>();
		for(Field field : cc.checksForFields.keySet()) {
			if(shouldExcludeField(field)) {
				fieldsToRemove.add(field);
			}
		}
		for(Field field : fieldsToRemove) {
			cc.checksForFields.remove(field);
		}
		return cc;
	}

	private boolean shouldExcludeField(Field field) {
		if(field.isAnnotationPresent(ValidateOn.class)) {
			for(ValidationType validationType : field.getAnnotation(ValidateOn.class).value()) {
				if(validationType.isType(request)) {
					return false;
				}
			}
		}

		Class clazz = field.getDeclaringClass();
		if(clazz.isAnnotationPresent(ValidateOn.class)) {
			for(ValidationType validationType : ((ValidateOn)clazz.getAnnotation(ValidateOn.class)).value()) {
				if(validationType.isType(request)) {
					return false;
				}
			}
		}

		return true;
	}
}
